/*
 * @Description: 管理员账号
 * @Author: HuiSir<273250950@qq.com>
 * @Date: 2021-09-07 16:10:06
 * @LastEditTime: 2025-09-16 17:38:35
 */
import { defineStore } from "pinia";
import { reactive, toRefs, computed } from "vue";
import { project } from "@/init/config";
import { doLogin } from "@/api/login/index";
import LocalCache from "@/utils/LocalCache";
import { fieldMapping } from "@/utils/common";
import { ElMessage } from "element-plus";
import router from "@/router";
import { usePermTreeHandler } from "../helpers";
import { doLogout } from "@/api/sys";

/**
 * 管理员state数据接口
 */
export interface AdminState extends Recordable {
  /**
   * 登录状态
   * 0-未登录 1-已登录 2-登录失效(弹出登陆框)
   */
  loginStatus?: 0 | 1 | 2;
  /**
   * 登陆失效时弹出登录框状态
   */
  showLoginModel: boolean;
  /**
   * Token 存这里和localStorage两处
   * 防止管理员在登录状态清理浏览器缓存
   */
  token?: string | null;
  /**
   * 缓存管理员信息
   * 刷新页面重新拉取
   */
  adminInfo?: AdminInfo | null;
  /**
   * 管理员所有功能权限（code数组）
   */
  funcPermCodes: string[];
  /**
   * 管理员所有菜单列表，只在侧栏菜单展示（非树）
   */
  menus: Permission[];
  /**
   * 新增的动态路由name列表
   */
  dynamicRoutes: string[];
}

export default defineStore("admin", () => {
  const state: AdminState = reactive({
    loginStatus: 0,
    showLoginModel: false,
    token: null,
    adminInfo: null,
    funcPermCodes: [],
    menus: [],
    dynamicRoutes: [],
  });

  /**
   * 获取登陆状态（是否已登录）
   */
  const isLogin = computed(() => state.loginStatus === 1);

  /**
   * 修改状态
   */
  const setStates = (obj: Record<string, unknown>) => {
    Object.keys(obj).forEach((key) => {
      state[key] = obj[key];
    });
  };
  /**
   * 修改token
   */
  const setToken = (token: string) => {
    state.token = token;
    LocalCache.setCache(project.storage.token, token);
  };
  /**
   * 删除token
   */
  const removeToken = () => {
    state.token = null;
    LocalCache.removeCache(project.storage.token);
  };
  /**
   * 清除登陆状态
   */
  const clearLoginState = () => {
    state.loginStatus = 0;
    state.token = null;
    state.adminInfo = null;
    state.showLoginModel = false;
    LocalCache.removeCache(project.storage.token);
  };
  /**
   * 登陆无效状态
   */
  const LoginInvalid = () => {
    state.loginStatus = 2;
    state.token = null;
    state.adminInfo = null;
    state.showLoginModel = true;
    LocalCache.removeCache(project.storage.token);
    console.warn("登陆已失效，请先登陆！");
  };
  /**
   * 清除菜单及路由
   */
  const clearAllMenuAndRoute = () => {
    // 清除路由
    state.dynamicRoutes.forEach((routeName: string) => {
      router.removeRoute(routeName);
    });
    // 清除菜单
    state.menus = [];
  };

  /**
   * 登录
   */
  const login = async (loginData: LoginForm) => {
    // 拷贝数据避免影响原数据，由于登陆数据比较简单，这里使用json进行拷贝
    const copyLoginData = JSON.parse(JSON.stringify(loginData));

    // 请求参数字段与配置项对齐
    fieldMapping({
      data: copyLoginData,
      fieldsMap: project.loginFields,
      reverse: true,
    });

    // 这里在Request.ts中已经存了token，所以无需再次读token
    // token一般在响应头中返回，不做数据明文
    const { ok, data } = await doLogin(copyLoginData);
    if (ok === 1) {
      // 处理登陆结果
      loginResHandler(data);

      // 关闭弹窗
      if (state.showLoginModel) {
        state.showLoginModel = false;
      }

      // 若为登录页，跳转到首页或query中的历史页
      const { name, query } = router.currentRoute.value;
      if (name === "Login") {
        // redirect携带全量参数，需转义为原参数
        router.replace(
          query.redirect ? decodeURIComponent(query.redirect as string) : "/"
        );
      }
    } else {
      // 登陆失败
      return Promise.reject();
    }
  };

  /**
   * 登出
   */
  const logout = async () => {
    const { ok } = await doLogout();
    if (ok) {
      ElMessage({ type: "success", message: "已登出" });
      // 清除登录状态已在路由钩子中处理，这里不处理
      router.replace({ name: "Login" });
    }
  };

  /**
   * 处理登陆结果
   */
  const loginResHandler = (adminInfo: AdminInfo) => {
    // 登录成功缓存管理员
    setStates({ loginStatus: 1, adminInfo });

    if (adminInfo?.permissionList) {
      // 生成动态路由
      const { dynamicRoutes, funcPermCodes, menus } = usePermTreeHandler(
        adminInfo.permissionList,
        router
      );

      // 设置缓存动态路由name
      setStates({ dynamicRoutes, funcPermCodes, menus });
    }
  };

  return {
    ...toRefs(state),
    isLogin,
    setStates,
    setToken,
    removeToken,
    clearLoginState,
    LoginInvalid,
    clearAllMenuAndRoute,
    login,
    logout,
    loginResHandler,
  };
});
